package org.enhance.web.util;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.enhance.common.exception.EnhanceRuntimeException;
import org.enhance.web.model.bo.Network;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

public class NetworkUtil {
	private NetworkUtil() {
		throw new IllegalStateException("Utility class");
	}

	private static List<Network> networks;

	public static boolean ipIsInNet(String srcIp, String ipArea) {
		if ("127.0.0.1".equals(srcIp)) {
			return true;
		}

		if(StringUtils.isBlank(ipArea)){
			return false;
		}

		for (String compareIp : ipArea.split(",")) {
			if(compareIpIsInNet(srcIp, compareIp)) {
				return true;
			}
		}
		return false;
	}

	public static boolean ipIsInNet(String srcIp, List<String> ipArea) {
		if ("127.0.0.1".equals(srcIp)) {
			return true;
		}

		if(CollectionUtils.isEmpty(ipArea)){
			return false;
		}

		for (String compareIp : ipArea) {
			if(compareIpIsInNet(srcIp, compareIp)) {
				return true;
			}
		}
		return false;
	}

	private static boolean compareIpIsInNet(String srcIp, String configIp) {
		if(StringUtils.isBlank(configIp)){
			return false;
		}

		if (!configIp.contains("/")) {
			return configIp.equals(srcIp);
		}

		String[] ips = srcIp.split("\\.");
		//ip地址的十进制值
		int ipAddress = (Integer.parseInt(ips[0]) << 24)
				| (Integer.parseInt(ips[1]) << 16)
				| (Integer.parseInt(ips[2]) << 8) | Integer.parseInt(ips[3]);
		//掩码（0-32）
		int type = Integer.parseInt(configIp.replaceAll(".*/", ""));
		//匹配的位数为32 - type位（16进制的1）
		int mask = 0xFFFFFFFF << (32 - type);
		String cidrIp = configIp.replaceAll("/.*", "");
		//网段ip十进制
		String[] cidrIps = cidrIp.split("\\.");
		int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24)
				| (Integer.parseInt(cidrIps[1]) << 16)
				| (Integer.parseInt(cidrIps[2]) << 8)
				| Integer.parseInt(cidrIps[3]);

		if((ipAddress & mask) == (cidrIpAddr & mask)){
			return true;
		}

		return false;
	}

	public static String getUserIp() {
		HttpServletRequest request = RequestUtil.getRequest();
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Forwarded-For");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Real-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		if (ip != null && ip.length() > 15) {
			// 多个ip第一个为真实ip
			if (ip.indexOf(",") > 0) {
				ip = ip.substring(0, ip.indexOf(","));
			}
		}
		return ip;
	}

	public static List<String> getServerIp() {
		List<String> serverIps = new ArrayList<>();
		List<Network> nets = innerGetNetworks();
		if (CollectionUtils.isEmpty(nets)) {
			serverIps.add("127.0.0.1");
		} else {
			for (Network net : nets) {
				List<String> hostAddresses = net.getHostAddresses();
				if(CollectionUtils.isNotEmpty(hostAddresses)) {
					serverIps.addAll(hostAddresses);
				}
			}
		}
		return serverIps;
	}

	public static List<String> getNetworks() {
		List<Network> nets = innerGetNetworks();
		if (CollectionUtils.isEmpty(nets)) {
			return Collections.emptyList();
		}
		List<String> netInfos = new ArrayList<>();
		for (Network network : nets) {
			netInfos.add(network.toString());
		}
		return netInfos;
	}

	private static List<Network> innerGetNetworks() {
		if (CollectionUtils.isEmpty(networks)) {
			networks = new ArrayList<>();
			try {
				Enumeration<NetworkInterface> faces = NetworkInterface.getNetworkInterfaces();
				while (faces.hasMoreElements()) { // 遍历网络接口
					NetworkInterface face = faces.nextElement();
					if (face.isLoopback() || face.isVirtual() || !face.isUp()) {
						continue;
					}

					Enumeration<InetAddress> address = face.getInetAddresses();
					List<String> hostAddresses = new ArrayList<>();
					while (address.hasMoreElements()) { // 遍历网络地址
						InetAddress addr = address.nextElement();
						if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress() && !addr.isAnyLocalAddress()) {
							hostAddresses.add(addr.getHostAddress());
						}
					}

					Network network = new Network();
					network.setDisplayName(face.getDisplayName());
					network.setHostAddresses(hostAddresses);
					networks.add(network);
				}
			} catch (SocketException e) {
				throw new EnhanceRuntimeException(e);
			}
		}
		return networks;
	}
}